Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Prototypes, Call, and Apply

Spread the love

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at prototypes, call , and apply .

Function Prototypes

Functions have a special prototype property that has items that are shared between all instances of the constructor function.

For instance, we can write:

function F() {}

F.prototype = {
  name: 'james',
  say() {
    return `I am ${this.nam}`;
  }
};

Then if we create 2 instances of F :

const foo = new F();
const bar = new F();
console.log(foo, bar);

We see that both foo and bar have the same properties.

The say method also does the same thing.

Methods of Function Objects

Function objects have their own methods.

For instance, functions have the toString method to return the string with the code of the function.

So if we have:

function add(a, b, c) {
  return a + b + c;
}

console.log(add.toString());

We get:

"function add(a, b, c) {
  return a + b + c;
}"

logged.

Call and Apply

Functions have the call and apply method to let us run functions, set the value of this and pass arguments to it.

For instance, if we have:

const obj = {
  name: 'james',
  say(who) {
    return `${this.name} is ${who}`;
  }
};

Then we can call say with call by writing:

const a = obj.say.call({
  name: 'mary'
}, 'female');

Then a is 'mary is female’ .

We set this to:

{
  name: 'mary'
}

so this.name is 'mary' .

The 2nd argument is the argument for say , so who is 'female' .

We can also call apply by doing the same thing, except that the arguments of the function are in the array.

For instance, we can write:

const obj = {
  name: 'james',
  say(who) {
    return `${this.name} is ${who}`;
  }
};

const a = obj.say.apply({
  name: 'mary'
}, ['female']);

and we get the same thing.

Lexical this in Arrow Functions

this is a dynamic object that changes according to its context.

Arrow functions don’t bind to its own value of this .

So if we have:

const obj = {
  prefix: "Hello",
  greet(names) {
    names.forEach(function(name) {
      console.log(`${this.prefix} ${name}`);
    })
  }
}

We’ll get an error with the greet method since this is the callback function, so it doesn’t have the prefix property.

But if we use an arrow function:

const obj = {
  prefix: "Hello",
  greet(names) {
    names.forEach((name) => {
      console.log(`${this.prefix} ${name}`);
    })
  }
}

Then the function works properly since it doesn’t bind to its own value of this .

Inferring Object Types

The toString method of Object.prototype gives us the class name that’s used to create an object.

For instance, we can write:

Object.prototype.toString.call({});

And get:

"[object Object]"

And if we write:

Object.prototype.toString.call([]);

We get:

"[object Array]"

We can use call with the toString method by writing:

Array.prototype.toString.call([1, 2, 3]);

We get:

"1,2,3"

This is the same as:

[1, 2, 3].toString()

Conclusion

The call and apply methods let us call functions with different values of this and arguments.

Also, the prototype has properties that are shared between all constructor instances.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *